<?php

namespace paymch\models;

use Yii;
use yii\db\Exception;
use common\models\trade\Trade;
use common\models\trade\TradeOrder;
use common\models\original\UserAccount;
use common\models\original\UserAccountLogs;
use common\helpers\Utils;

/**
 * 异常交易退款
 * AbnormalRefund is the model behind the alipay async notify form.
 * 
 * @author emhome <emhome@163.com>
 * @since 2.0
 */
class AbnormalRefund extends BasePaymentModel {

    /**
     * 交易中心分配给商户的应用ID
     * @var string(16) 交易中心分配给商户的应用ID
     * @example 72300007148
     * @static 是
     */
    public $app_id;

    /**
     * 签名类型
     * @var string(10) 商户生成签名字符串所使用的签名算法类型，目前支持RSA2和RSA，推荐使用RSA2
     * @example RSA2
     * @static 是
     */
    public $sign_type;

    /**
     * 请求签名
     * @var string(256) 请参考异步返回结果的验签
     * @example 601510b7970e52cc63db0f44997cf70e
     * @static 是
     */
    public $sign;

    /**
     * 编码格式
     * @var string(10) 编码格式，如utf-8、gbk、gb2312等
     * @example utf-8
     * @static 是
     */
    public $charset;

    /**
     * 接口版本
     * @var string(3) 调用的接口版本，固定为：1.0
     * @example 1.0
     * @static 是
     */
    public $version;

    /**
     * 异常交易ID
     * @var Int(11) 
     * @example 1
     * @static 是
     */
    public $abnormal_id;
    //
    private $_partner = null;
    private $_tradeOrder = null;

    /**
     * 交易中心统一下单请求参数校验
     * @inheritdoc
     */
    public function rules() {
        return [
            [['sign_type', 'sign', 'charset', 'version', 'app_id', 'abnormal_id'], 'required'],
            [['sign_type', 'charset', 'version', 'app_id'], 'string', 'max' => 16],
            ['abnormal_id', 'integer'],
            //校验APPID
            ['app_id', 'validateAppId'],
            //验证下单请求签名
            ['sign', 'validateSignature'],
            //验证异常交易订单是否存在
            ['abnormal_id', 'validateAbnormalOrder'],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels() {
        return [
            'app_id' => '交易中心分配给商户的应用ID',
            'charset' => '编码格式',
            'version' => '接口版本',
            'sign_type' => '签名类型',
            'sign' => '签名',
            'abnormal_id' => '异常交易ID',
        ];
    }

    /**
     * Validates the APPID.
     * 验证app_id是否为该商户本身
     *
     * @param string $attribute the attribute currently being validated
     */
    public function validateAppId($attribute) {
        if (!$this->hasErrors()) {
            $partner = $this->getPartner();
            if (!$partner) {
                $this->addError($attribute, '未签约商户！');
            } else {
                $this->_partner = $partner;
            }
        }
    }

    /**
     * Validates the signature.
     * 校验请求的签名
     *
     * @param string $attribute the attribute currently being validated
     */
    public function validateSignature($attribute) {
        if (!$this->hasErrors()) {
            $paymchServer = new \common\components\paymch\MchServer([
                'appId' => $this->app_id,
                'version' => $this->version,
                'charset' => $this->charset,
                'rsaPublicKeyFilePath' => Yii::getAlias('@common') . '/data/keys/emchpay/rsa_public_key.pem',
            ]);
            $flag = $paymchServer->checkSignature($this->attributes, 'RSA2');
            if (!$flag) {
                $this->addError($attribute, '请求签名校验失败！');
            }
        }
    }

    /**
     * Validates the Abnormal ID
     * 商户需要验证该通知数据中的bizno是否为商户系统中创建的订单号
     *
     * @param string $attribute the attribute currently being validated
     */
    public function validateAbnormalOrder($attribute) {
        if (!$this->hasErrors()) {
            $tradeOrder = $this->getTradeOrder();
            if ($tradeOrder == null) {
                $this->addError($attribute, '异常交易订单信息不存在或状态已变更！');
            }
        }
    }

    /**
     * Find Partner by [[appid]]
     *
     * @return \common\models\trade\Partner|null
     */
    protected function getPartner() {
        if ($this->_partner === null) {
            $this->_partner = \common\models\trade\Partner::findByAppId($this->app_id);
        }
        return $this->_partner;
    }

    /**
     * Finds trade by [[trade_no]]
     *
     * @return Trade|null
     */
    protected function getTradeOrder() {
        if ($this->_tradeOrder === null) {
            $this->_tradeOrder = TradeOrder::findOne([
                'id' => $this->abnormal_id,
                'balance' => TradeOrder::BALANCE_REFUND,
                'status' => Trade::STATUS_DEFAULT,
            ]);
        }
        return $this->_tradeOrder;
    }

    /**
     * 关闭交易提交保存
     * @return bool whether the email was sent
     */
    public function save(&$msg) {
        if (!$this->validate()) {
            $msg = Utils::arrayToString($this->firstErrors, false);
            return false;
        }
        $model = $this->tradeOrder;
        $originalTrade = $model->trade;
        if (!$originalTrade) {
            $msg = '原始交易不存在！';
            return false;
        }
        parent::invokeLog('[' . $model->id . ']AbnormalRefund', $model->attributes);

        $paymode = $model->paymode;
        if ($paymode !== TradeOrder::PAYMODE_CREDIT) {
            if (bccomp($originalTrade->cash, $model->pay, 2) != 0) {
                $msg = '退款金额和支付金额不一致！';
                return false;
            }
            $request = [
                "out_trade_no" => $model->original_no,
                "amount" => $originalTrade->cash,
                "refund" => $model->pay,
                "reason" => $model->mark,
                "refund_no" => $model->trade->trade_no,
            ];
            parent::invokeLog('[' . $model->id . ']AbnormalRefund Request Data', $request);
            //第三方支付平台退款
            $msg = RefundHandler::$paymode($request);
            return true;
        } else {
            //直接退积分
            return RefundHandler::credit($model, $msg);
        }
    }

}
